#ifndef _NSA_H
#define _NSA_H
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <string.h>
#include <linux/list.h>

#include "nsa_api.h"

#define NSA_DRV_VERSION     "1.00"

struct nsa_enabler;

/*
struct nsa_q {								
	struct sk_buff *queue;
	int type;
	int maxlen, limit;
};
*/

#define NSA_PACKET_T                0x1
#define NSA_SESSION_T               0x2
#define NSA_LOG_T                   0x3
#define NSA_AGING_T                 0x4
#define NSA_COUNTER_T               0x5

#define	QUEUE_RX_T					0
#define	QUEUE_AGE_T					1
#define	QUEUE_LOG_T					2
#define	QUEUE_STA_T					3

#define QUEUE_GENERIC				4
#define QUEUE_MIRROR				5
#define QUEUE_HOST					6
#define QUEUE_FIRST 			    7

#define QUEUE_TX_T                  8

#define QUEUE_MAX                   QUEUE_TX_T+1

#define nsa_q_full(q) (((q)->queue).qlen>=(q)->limit)

struct nsa_drv_stats{
	u_int64_t rx_pkts_first;
	u_int64_t rx_pkts_host;
	u_int64_t rx_pkts_mirror;
	u_int64_t rx_pkts_general;
	u_int64_t rx_pkts;

	u_int64_t age_pkts;
	u_int64_t sta_pkts;
    u_int64_t age_pkts_drop;
    u_int64_t sta_pkts_drop;

	u_int64_t rx_drop_first;
	u_int64_t rx_drop_host;
	u_int64_t rx_drop_mirror;
	u_int64_t rx_drop_general;

	u_int64_t tx_pkts_packet;
	u_int64_t tx_pkts_ssn;

	u_int64_t tx_len_sso;
	u_int64_t tx_entry_sso;
	u_int64_t tx_num_sso;

	u_int64_t tx_move;

};

struct nsa_error_stat {
	int wrong_dev;    	  	
	int unknown_dev;		/* rx ifn is not in between [1-7]*/
	int tx_plain_busy;	  	/* tx ring full, plain packet*/
	int tx_ssn_busy;	  	/* tx ring full, with ssn packet*/
	int tx_sso_busy;		/* tx ring full, sso*/			
	int tx_new_skb;			/* in tx, new skb (e.g. align packet) failed*/

};

struct nsa_dev{
    /* Initiated from NSA's birth information */
    struct nsa_dna dna;
    u_int32_t hw_dna;        /* nsa dna code, given by NSA's silicon */
    u_int32_t ports;
    u_int32_t status;		/*status of this card*/

    /* Initiated from npcp controller's registering */
    int dev_id;         /* nsa device id*/
    int *msg_enable;     /* derived from npcp_controller */
    struct npcp_controller *sci;

    
//    struct nsa_q queue[QUEUE_MAX];
#define MAX_NSA_SSN_CACHE_ENTRIES   4
#define NSA_SSN_ENTRY_DEPTH         4
//    struct sk_buff *cache_pos[MAX_NSA_SSN_CACHE_ENTRIES];
    int cache_index[MAX_NSA_SSN_CACHE_ENTRIES];

    struct nsa_drv_stats drv_stats;
    struct nsa_error_stat error;
    
//	struct nsa_enabler *nsa_handler;

    /* Initiated when nsa device got ready */
	struct net_device **spis;

    /* if hardware communication error occurs... */
 //   struct work_struct reset_task;

    /**/
//  struct sk_buff *hold;
};


/* phy operation can only be used with kernel.
 * In NSA, phy means SempSec internal access to 
 * physical port while mido refers to "PHY"
 * silicon external to SempSec
 */
struct nsa_phy{
    int nsa_id;
#define PHY_SPEED_10	0
#define PHY_SPEED_100	1
#define PHY_SPEED_1000	2
	union {
		struct {
			unsigned int 
			    rx_enable:1,
				tx_enable:1,
				frame_interval:1,
				loop:1,
				speed:2,
				rsv:26;
		};
		unsigned int data;
	};
};

#define nsa_sci(nsa) nsa->sci
#define sci_nsa(sci) (struct nsa_dev*)((sci)->np_dev)

#endif /*_NSA_H*/
